package com.aviator.detective.model.rule;

import com.aviator.detective.model.ExecuteElement;
import com.aviator.detective.model.NodeState;
import com.aviator.detective.model.SourceCell;
import com.aviator.detective.model.SourceType;
import com.aviator.detective.model.variable.ExpressVariable;
import com.google.common.base.Preconditions;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 规则模型
 */
public class Rule implements ExecuteElement, SourceCell {
    private String id;
    private String name;
    private String alias;
    private String script;
    private String bindRuleResultFlag;
    private NodeState state;
    private List<ExpressVariable> variableList = new CopyOnWriteArrayList<>();

    public List<ExpressVariable> getVariableList(){
        return Collections.unmodifiableList(variableList);
    }

    public void addExpressVariable(ExpressVariable expressVariable){
        variableList.add(expressVariable);
    }

    public void removeExpressVariable(ExpressVariable expressVariable){
        if (variableList.contains(expressVariable)){
            variableList.remove(expressVariable);
        }
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
        this.bindRuleResultFlag = bindRuleResultFlag;
    }


    public void setName(String name) {
        this.name = name;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getScript() {
        return script;
    }

    public void setScript(String script) {
        this.script = script;
    }

    public NodeState getState() {
        return state;
    }

    public void setState(NodeState state) {
        this.state = state;
    }

    public String getBindRuleResultFlag() {
        return bindRuleResultFlag;
    }

    @Override
    public String getExecuteElementName() {
        return this.name;
    }

    @Override
    public SourceType getType() {
        return SourceType.RULE;
    }

    /**
     * if(true){
     *     variable1;
     *     variable2;
     * }
     * @return
     */
    @Override
    public String toAviatorScript() {
        Preconditions.checkNotNull(script == null || script == "","rule script not be null or empty");
        Preconditions.checkArgument(bindRuleResultFlag == null || bindRuleResultFlag =="","bindRuleResultFlag not be null or empty");
        StringBuffer aviatorScript = new StringBuffer();
        aviatorScript.append(lhs());
        aviatorScript.append("\\n");
        if (variableList !=null && variableList.size()>0){
            aviatorScript.append(rhs());
        }
        return script.toString();
    }

    /**
     * let aaa = {a>b && c<d};
     * 条件
     * @return
     */
    public String lhs(){
        StringBuffer lhsScript = new StringBuffer(LET).append(PADDING).append(this.bindRuleResultFlag).append(EQUAL);
        lhsScript.append(LEFT_BRACE).append(this.script).append(RIGHT_BRACE).append(SEMICOLON);
        return lhsScript.toString();
    }

    /**
     * if(aaa){
     *     variable1({c=a+b});
     *     variable2({d=d-c}
     *     variable3({decisionResult='AP'}));
     * }
     * 绑定变量
     * @return
     */
    public String rhs(){
        StringBuffer rhsScript = new StringBuffer(IF).append(LEFT_PARENTHESES).append(this.bindRuleResultFlag).append(RIGHT_PARENTHESES);
        rhsScript.append(LEFT_BRACE).append("\\n");
        for (ExpressVariable expressVariable : variableList) {
            rhsScript.append(expressVariable.toAviatorScript())
                    .append(SEMICOLON)
                    .append("\\n");
        }
        rhsScript.append(RIGHT_BRACE);
        return rhsScript.toString();
    }
}
